<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>八方拖动改变宽高</title>
    <style>
      #box {
        position: absolute;
        top: 100px;
        left: 100px;
        width: 100px;
        height: 100px;
        background-color: red;
        cursor: pointer;
        user-select: none;
      }
    </style>
  </head>
  <body>
    <div id="box"></div>
    <script>
      const box = document.querySelector("#box");
      let dir = "";
      let isDown = false;
      let mes = {};
      let boundary = 10;

      function onMousedown(ev) {
        isDown = true;

        const { width, height, left, top, right, bottom } = getPos(box);

        mes = {
          x: ev.clientX,
          y: ev.clientY,
          w: width,
          h: height,
          t: top,
          r: right,
          b: bottom,
          l: left,
        };
      }
      function onMousemove(ev) {
        const { width, height, left, top, right, bottom } = getPos(box);

        if (!isDown) {
          // 防止下面的不断叠加字符
          dir = "";
          // 鼠标在边界之内
          box.style.cursor = "auto";

          // 鼠标没有按下，在盒子边缘改变鼠标样式,表明此时可以改变盒子的宽高
          if (ev.clientY < top + boundary) {
            // 距离上边界
            dir += "n";
          }

          if (ev.clientY > bottom - boundary) {
            // 距离下边界
            dir += "s";
          }

          if (ev.clientX < left + boundary) {
            // 距离左边界
            dir += "w";
          }

          if (ev.clientX > right - boundary) {
            // 距离右边界
            dir += "e";
          }

          // dir 的 + 是就可以覆盖到四个角了，因此注意上面的顺序
          box.style.cursor = `${dir}-resize`;
        } else {
          // 鼠标按下
          if (dir.indexOf("e") !== -1) {
            // 右边界拖动
            let w = mes.w + ev.clientX - mes.x;

            // 小于某个数值，不让改变宽度了
            if (w < 100) {
              w = 100;
            }
            box.style.width = w + "px";
          }

          if (dir.indexOf("s") !== -1) {
            // 下边界拖动
            let h = mes.h + ev.clientY - mes.y;

            // 小于某个数值，不让改变高度了
            if (h < 100) {
              h = 100;
            }
            box.style.height = h + "px";
          }

          if (dir.indexOf("w") !== -1) {
            // 左边界拖动
            let w = mes.w + mes.x - ev.clientX;
            let l = mes.l - (mes.x - ev.clientX);

            // 小于某个数值，不让改变宽度了
            if (w < 100) {
              w = 100;
              // 不让移动
              // l = mes.l;
              l = mes.r - 100;
            }

            box.style.width = w + "px";
            box.style.left = l + "px";
          }

          if (dir.indexOf("n") !== -1) {
            // 上边界拖动
            let h = mes.h + mes.y - ev.clientY;
            let t = mes.t - (mes.y - ev.clientY);

            // 小于某个数值，不让改变高度了
            if (h < 100) {
              h = 100;
              // 不让移动
              // t = mes.t;
              t = mes.b - 100;
            }

            box.style.height = h + "px";
            box.style.top = t + "px";
          }
        }
      }
      function onMouseup(ev) {
        isDown = false;
      }

      box.addEventListener("mousedown", onMousedown, false);
      document.addEventListener("mousemove", onMousemove, false);
      document.addEventListener("mouseup", onMouseup, false);

      function getPos(o) {
        return o.getBoundingClientRect();
      }
    </script>
  </body>
</html>
